﻿using SuperX.Common.Log;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.IO;
using System.Text;

namespace SuperX.Helper.FileUtil
{
    public static class ZipHelper
    {
        static ZipHelper()
        {
            ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
        }

        /// <summary>
        /// 文件解压
        /// </summary>
        /// <param name="zipFilePath"></param>
        /// <param name="extractPath"></param>
        /// <returns></returns>
        public static void Decompress(string zipFilePath = "", string extractPath = "")
        {
            try
            {
                //设置解压文件夹
                //extractPath = Path.Combine(extractPath, Path.GetFileNameWithoutExtension(zipFilePath));

                using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipFilePath)))
                {
                    ZipEntry entry;

                    if (!Directory.Exists(extractPath))
                        Directory.CreateDirectory(extractPath);
                    while ((entry = zipStream.GetNextEntry()) != null)
                    {
                        string outputPath = Path.Combine(extractPath, entry.Name);

                        if (entry.IsDirectory)
                        {
                            Directory.CreateDirectory(outputPath);
                        }
                        else
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
                            using (FileStream outputStream = File.Create(outputPath))
                            {
                                byte[] buffer = new byte[4096];
                                int bytesRead;

                                while ((bytesRead = zipStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    outputStream.Write(buffer, 0, bytesRead);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorException(ex);
            }
        }

        public static bool FileExists(string zipFilePath, string extension)
        {
            var result = false;
            using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipFilePath)))
            {
                ZipEntry entry;
                while ((entry = zipStream.GetNextEntry()) != null)
                {
                    if (!entry.IsDirectory && !string.IsNullOrEmpty(entry.Name) && Path.GetExtension(entry.Name) == extension)
                        return true;
                }
            }
            return result;
        }

        public static void UnZIP(string zipFilePath = "", string extractPath = "")
        {
            try
            {
                using (ZipFile zipFile = new ZipFile(zipFilePath))
                {
                    // 设置解压目标文件夹
                    //zipFile.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;

                    // 遍历ZIP文件中的每个条目
                    foreach (ZipEntry entry in zipFile)
                    {
                        // 确定解压后的文件路径
                        string entryFilePath = Path.Combine(extractPath, entry.Name);

                        // 创建目录（如果需要）
                        if (entry.IsDirectory)
                        {
                            Directory.CreateDirectory(entryFilePath);
                        }
                        else
                        {
                            // 创建目录（如果需要）
                            Directory.CreateDirectory(Path.GetDirectoryName(entryFilePath));

                            // 解压文件
                            using (Stream inputStream = zipFile.GetInputStream(entry))
                            using (FileStream outputStream = File.Create(entryFilePath))
                            {
                                byte[] buffer = new byte[4096];
                                int bytesRead;
                                while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    outputStream.Write(buffer, 0, bytesRead);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("解压失败： " + ex.Message);
            }
        }

        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="zipFilePath"></param>
        /// <param name="level">The new compression level (1 to 9).</param>
        public static void Compress(string sourcePath = "", string zipFilePath = "", int level = 5)
        {
            try
            {
                using (FileStream zipStream = new FileStream(zipFilePath, FileMode.Create))
                {
                    using (ZipOutputStream zipOut = new ZipOutputStream(zipStream))
                    {
                        zipOut.SetLevel(level); // 压缩级别

                        // 遍历源文件夹
                        foreach (string file in Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories))
                        {
                            string relativePath = file.Substring(sourcePath.Length + 1);

                            ZipEntry entry = new ZipEntry(relativePath);
                            entry.DateTime = DateTime.Now;
                            entry.Size = new FileInfo(file).Length;

                            zipOut.PutNextEntry(entry);

                            using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                            {
                                byte[] buffer = new byte[4096];
                                int bytesRead;

                                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    zipOut.Write(buffer, 0, bytesRead);
                                }
                            }
                        }
                        zipOut.Finish();
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorException(ex);
            }
        }
    }
}